All files / web/src/app/api/classrooms/[classroomId]/enroll-by-family-code route.ts

0% Statements 0/119
0% Branches 0/1
0% Functions 0/1
0% Lines 0/119

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120                                                                                                                                                                                                                                               
import { eq } from 'drizzle-orm'
import { NextResponse } from 'next/server'
import { db, schema } from '@/db'
import {
  createEnrollmentRequest,
  getLinkedParentIds,
  getTeacherClassroom,
  isEnrolled,
} from '@/lib/classroom'
import { getSocketIO } from '@/lib/socket-io'
import { getUserId } from '@/lib/viewer'
import { withAuth } from '@/lib/auth/withAuth'

/**
 * POST /api/classrooms/[classroomId]/enroll-by-family-code
 * Teacher looks up a student by family code and creates an enrollment request
 *
 * Body: { familyCode: string }
 * Returns: { success: true, request, player } or { success: false, error }
 */
export const POST = withAuth(async (req, { params }) => {
  try {
    const { classroomId } = (await params) as { classroomId: string }
    const userId = await getUserId()
    const body = await req.json()

    if (!body.familyCode) {
      return NextResponse.json({ success: false, error: 'Missing familyCode' }, { status: 400 })
    }

    // Verify user is the teacher of this classroom
    const classroom = await getTeacherClassroom(userId)
    if (!classroom || classroom.id !== classroomId) {
      return NextResponse.json({ success: false, error: 'Not authorized' }, { status: 403 })
    }

    // Look up player by family code
    const normalizedCode = body.familyCode.toUpperCase().trim()
    const player = await db.query.players.findFirst({
      where: eq(schema.players.familyCode, normalizedCode),
    })

    if (!player) {
      return NextResponse.json(
        { success: false, error: 'No student found with that family code' },
        { status: 404 }
      )
    }

    // Check if already enrolled
    const alreadyEnrolled = await isEnrolled(classroomId, player.id)
    if (alreadyEnrolled) {
      return NextResponse.json(
        {
          success: false,
          error: 'This student is already enrolled in your classroom',
        },
        { status: 400 }
      )
    }

    // Create enrollment request (teacher-initiated, requires parent approval)
    const request = await createEnrollmentRequest({
      classroomId,
      playerId: player.id,
      requestedBy: userId,
      requestedByRole: 'teacher',
    })

    // Emit socket event for real-time updates
    const io = await getSocketIO()
    if (io) {
      try {
        const eventData = {
          request: {
            id: request.id,
            classroomId,
            classroomName: classroom.name,
            playerId: player.id,
            playerName: player.name,
            requestedByRole: 'teacher',
          },
        }

        // Emit to classroom channel (for teacher's view)
        io.to(`classroom:${classroomId}`).emit('enrollment-request-created', eventData)
        console.log(
          `[Enroll by Family Code API] Teacher created enrollment request for ${player.name}`
        )

        // Also emit to parent's user channel so they see the pending approval
        const parentIds = await getLinkedParentIds(player.id)
        for (const parentId of parentIds) {
          io.to(`user:${parentId}`).emit('enrollment-request-created', eventData)
          console.log(`[Enroll by Family Code API] Notified parent ${parentId} of new request`)
        }
      } catch (socketError) {
        console.error('[Enroll by Family Code API] Failed to broadcast:', socketError)
      }
    }

    return NextResponse.json({
      success: true,
      request,
      player: {
        id: player.id,
        name: player.name,
        emoji: player.emoji,
        color: player.color,
      },
    })
  } catch (error) {
    console.error('Failed to enroll by family code:', error)
    return NextResponse.json(
      { success: false, error: 'Failed to create enrollment request' },
      { status: 500 }
    )
  }
})